/* 
 * AUTHOR: Kevin Lam
 */

package com.apps.datastore;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.apps.datastore.dao.DepartmentInformationObject;
import com.apps.datastore.dao.AccountObject;
import com.apps.datastore.dao.ContactInformationObject.CARRIER;
import com.apps.datastore.dao.SectionInformationObject;
import com.apps.datastore.dao.SubscriptionFeedObject;
import com.apps.datastore.dao.SubscriptionInformationObject;
import com.apps.datastore.dao.WorklistItemObject;
import com.apps.utils.BCryptUtils;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Text;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.SortDirection;



public class AccountInformationDatastore {

	
	private static final String DATASTORE_ENTITY_SET_NAME= "Account Information Data Set";
	private static final String DATASTORE_ENTITY_KEY_NAME= "Account_Information_DATA";
	
	//Account Entity
	private static final String ACCOUNT_KIND = "Accounts";
	
	//Account property name
	private static final String ACCOUNT_ID_PROPERTY= "Email Address";
	private static final String PASSWORD_PROPERTY = "Password";
	private static final String ACTIVATED_PROPERTY = "Activated";
	private static final String AUTHENTICATION_KEY_PROPERTY="Authentication Key";
	
	//Account preferences
	private static final String PREFERENCE_NOTIFY_CONFIG_PROPERTY= "Notify Config";
	private static final String PREFERENCE_PHONE_NUMBER_PROPERTY= "Phone Number";
	private static final String PREFERENCE_CARRIER_PROPERTY= "Carrier";
	
	//Subscription Entities
	private static final String SUBSCRIPTION_KIND = "Subscriptions";
	
	private static final String FEED_KIND = "Feeds";
		
	//Subscription properties
	private static final String SUBSCRIPTION_EMAIL_PROPERTY = "Email";
	private static final String SUBSCRIPTION_STATUS_PROPERTY = "Status";
	
	//Subscription statuses
	public static final String SUBSCRIPTION_STATUS_WAITING = "Waiting";
	public static final String SUBSCRIPTION_STATUS_PENDING = "Pending";
	public static final String SUBSCRIPTION_STATUS_ACTIVE = "Active";
	
	private static final String FEED_READ_STATUS_PROPERTY = "Read";
	private static final String FEED_MESSAGE_PROPERTY = "Message";
	private static final String FEED_TIMESTAMP_PROPERTY = "Timestamp";
	
	//Worklist item entity
	private static final String WORKLIST_ITEM_KIND = "Worklist Item";
	
	//Worklist item properties
	private static final String WORKLIST_ITEM_DEPT_PROPERTY = "Department Id";
	private static final String WORKLIST_ITEM_COURSE_PROPERTY = "Course Id";
	private static final String WORKLIST_ITEM_SECTION_PROPERTY = "Section Id";
		
	//Account preferences
	
	private DatastoreService datastore;
	private UBCCourseSpiderDatastore spiderDatastore = new UBCCourseSpiderDatastore();
	
	public AccountInformationDatastore(){
		datastore=DatastoreServiceFactory.getDatastoreService();
		initSchema();
	}

	public void initSchema(){
		Query q = new Query(DATASTORE_ENTITY_SET_NAME);
		q.setKeysOnly();
		if(datastore.prepare(q).asSingleEntity() == null) {
			Transaction txn = datastore.beginTransaction();    
			Entity e = new Entity(DATASTORE_ENTITY_SET_NAME, DATASTORE_ENTITY_KEY_NAME);
			datastore.put(e);
			txn.commit();
		}
	}

	
	public void traceSchema() {
		Query q = new Query();
		Key k = KeyFactory.createKey(DATASTORE_ENTITY_SET_NAME, DATASTORE_ENTITY_KEY_NAME);
		q.setAncestor(k);
		q.setKeysOnly();
		List<Entity> l = datastore.prepare(q).asList(
				FetchOptions.Builder.withDefaults());
		for (Iterator i = l.iterator(); i.hasNext();) {
			Entity e = (Entity) i.next();
			System.out.println(e.getKey().toString());
		}
	}
	
	public void dropSchema() {
		Query q = new Query();
		Key k = KeyFactory.createKey(DATASTORE_ENTITY_SET_NAME, DATASTORE_ENTITY_KEY_NAME);
		q.setAncestor(k);
		q.setKeysOnly();
		List<Entity> l = datastore.prepare(q).asList(
				FetchOptions.Builder.withDefaults());
		for (Iterator i = l.iterator(); i.hasNext();) {
			Entity e = (Entity) i.next();
			System.out.println("deleting " + e.getKey());
			datastore.delete(e.getKey());
		}
	}
	
	
	public boolean addAccount(AccountObject ao){
		if(!this.checkAccountExist(ao.getEmail())){
			//create and commit this entry
			Key k = KeyFactory.createKey(DATASTORE_ENTITY_SET_NAME, DATASTORE_ENTITY_KEY_NAME); 
			Transaction txn = datastore.beginTransaction();                                
			Entity e = new Entity(ACCOUNT_KIND,k);                                       
			e.setProperty(ACCOUNT_ID_PROPERTY, ao.getEmail());     
			e.setProperty(PASSWORD_PROPERTY, ao.getPassword());
			e.setProperty(ACTIVATED_PROPERTY, ao.isActivated());
			e.setProperty(AUTHENTICATION_KEY_PROPERTY, ao.getAuthkey());
			e.setProperty(PREFERENCE_NOTIFY_CONFIG_PROPERTY, ao.getNotifyConfig());
			e.setProperty(PREFERENCE_PHONE_NUMBER_PROPERTY, ao.getPhoneNumber());
			e.setProperty(PREFERENCE_CARRIER_PROPERTY, ao.getCarrier().getGateway());
			datastore.put(e);                                                              
			txn.commit();                                                                  
			return true;
		}
		return false; 
	}
	
	public boolean checkAccountExist(String email){
		PreparedQuery query=queryAccount(email);
		if(query.countEntities(FetchOptions.Builder.withDefaults())==0){
			return false;
		}
		return true;
		
	}
	
	public boolean activateAccount(String email, String authKey){
		PreparedQuery pq = queryAccount(email);
		Entity e = pq.asSingleEntity();
		if (e == null)
			return false;
		if(!e.getProperty(AUTHENTICATION_KEY_PROPERTY).equals(authKey))
			return false;
		if(e.getProperty(ACTIVATED_PROPERTY).equals(true))
			return false;
		Transaction txn = datastore.beginTransaction();
		e.setProperty(ACTIVATED_PROPERTY, true);
		datastore.put(e);
		txn.commit();
		return true;
	}
	
	private PreparedQuery queryAccount(String email){
		Query q = new Query(ACCOUNT_KIND);
		q.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, email);
		return datastore.prepare(q);
	}
	
	public AccountObject getAccountObject(String accountId) {
		if(accountId == null)
			return null;
		Query q = new Query(ACCOUNT_KIND);
		q.addFilter(ACCOUNT_ID_PROPERTY, Query.FilterOperator.EQUAL, accountId);
		Entity qe = datastore.prepare(q).asSingleEntity();
		if(qe == null)
			return null;
		String password = (String) qe.getProperty(PASSWORD_PROPERTY);
		boolean active = (Boolean) qe.getProperty(ACTIVATED_PROPERTY);
		String authKey=(String) qe.getProperty(AUTHENTICATION_KEY_PROPERTY);
		long notifyConfig = (Long)qe.getProperty(PREFERENCE_NOTIFY_CONFIG_PROPERTY);
		String phoneNumber = (String)qe.getProperty(PREFERENCE_PHONE_NUMBER_PROPERTY);
		CARRIER carrier = CARRIER.get((String)qe.getProperty(PREFERENCE_CARRIER_PROPERTY));
		return new AccountObject(accountId,password,active,authKey, notifyConfig, phoneNumber, carrier);
	}
	
	public boolean updateAccountObject(AccountObject lao){
		Query q = new Query(ACCOUNT_KIND);
		q.addFilter(ACCOUNT_ID_PROPERTY, Query.FilterOperator.EQUAL, lao.getEmail());
		Entity qe = datastore.prepare(q).asSingleEntity();
		if(qe == null)
			return false;
		Transaction txn = datastore.beginTransaction();   
		qe.setProperty(PASSWORD_PROPERTY, lao.getPassword());
		qe.setProperty(AUTHENTICATION_KEY_PROPERTY, lao.getAuthkey());
		qe.setProperty(PREFERENCE_NOTIFY_CONFIG_PROPERTY, lao.getNotifyConfig());
		qe.setProperty(PREFERENCE_PHONE_NUMBER_PROPERTY, lao.getPhoneNumber());
		qe.setProperty(PREFERENCE_CARRIER_PROPERTY, lao.getCarrier().getGateway());
		datastore.put(qe);
		txn.commit();
		return true;
	}
	
	//Bi-directional subscription adding
	public boolean addSubscription(String from, String to){
		Query q_from = new Query(ACCOUNT_KIND);
		q_from.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, from);
		q_from.setKeysOnly();
		PreparedQuery pq_from = datastore.prepare(q_from);
		Entity e_from = pq_from.asSingleEntity();
		
		Query q_to = new Query(ACCOUNT_KIND);
		q_to.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, to);
		q_to.setKeysOnly();
		PreparedQuery pq_to = datastore.prepare(q_to);
		Entity e_to = pq_to.asSingleEntity();
		
		if(e_from == null || e_to == null)
			return false;
		Key k_from = e_from.getKey();
		Key k_to = e_to.getKey();
		if(checkSubscriptionExists(k_from, from, k_to, to))
			return false;
		Transaction txn = datastore.beginTransaction(); 
		Entity sub_from = new Entity(SUBSCRIPTION_KIND, k_from);
		sub_from.setProperty(SUBSCRIPTION_EMAIL_PROPERTY, to);
		//When first add, set a pending request
		sub_from.setProperty(SUBSCRIPTION_STATUS_PROPERTY, "Waiting");
		datastore.put(sub_from);
		Entity sub_to = new Entity(SUBSCRIPTION_KIND, k_to);
		sub_to.setProperty(SUBSCRIPTION_EMAIL_PROPERTY, from);
		sub_to.setProperty(SUBSCRIPTION_STATUS_PROPERTY, "Pending");
		datastore.put(sub_to);
		txn.commit();
		return true;
	}
	
	//Bidirectional email check
	public boolean checkSubscriptionExists(String from, String to){
		Query q_from = new Query(ACCOUNT_KIND);
		q_from.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, from);
		q_from.setKeysOnly();
		PreparedQuery pq_from = datastore.prepare(q_from);
		Entity e_from = pq_from.asSingleEntity();
		Key from_key = e_from.getKey();
		
		Query q_to = new Query(ACCOUNT_KIND);
		q_to.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, to);
		q_to.setKeysOnly();
		PreparedQuery pq_to = datastore.prepare(q_to);
		Entity e_to = pq_to.asSingleEntity();
		Key to_key = e_to.getKey();
		
		Query sub_from = new Query(SUBSCRIPTION_KIND);
		sub_from.setAncestor(from_key);
		sub_from.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, to);
		sub_from.addFilter(SUBSCRIPTION_STATUS_PROPERTY, FilterOperator.EQUAL, SUBSCRIPTION_STATUS_ACTIVE);
		sub_from.setKeysOnly();
		PreparedQuery sub_pq_from = datastore.prepare(sub_from);
		
		Query sub_to = new Query(SUBSCRIPTION_KIND);
		sub_to.setAncestor(to_key);
		sub_to.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, from);
		sub_from.addFilter(SUBSCRIPTION_STATUS_PROPERTY, FilterOperator.EQUAL, SUBSCRIPTION_STATUS_ACTIVE);
		sub_to.setKeysOnly();
		PreparedQuery sub_pq_to = datastore.prepare(sub_to);
		
		if(sub_pq_from.asSingleEntity() != null || sub_pq_to.asSingleEntity() != null )
			return true;
		return false;
		
	}
	
	//Bidirectional check
	private boolean checkSubscriptionExists(Key from_key, String from, Key to_key, String to){
		Query q_from = new Query(SUBSCRIPTION_KIND);
		q_from.setAncestor(from_key);
		q_from.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, to);
		q_from.setKeysOnly();
		PreparedQuery pq_from = datastore.prepare(q_from);
		
		Query q_to = new Query(SUBSCRIPTION_KIND);
		q_to.setAncestor(to_key);
		q_to.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, from);
		q_to.setKeysOnly();
		PreparedQuery pq_to = datastore.prepare(q_to);
		if(pq_from.asSingleEntity() != null || pq_to.asSingleEntity() != null )
			return true;
		return false;
	}
	
	//Bidirectional subscription activation
	public boolean activateSubscription(String from, String to) {
		Query q_from = new Query(ACCOUNT_KIND);
		q_from.setKeysOnly();
		q_from.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, from);
		PreparedQuery from_key = datastore.prepare(q_from);
		Entity e_from = from_key.asSingleEntity();
		if(e_from == null)
			return false;
		Key key_from = e_from.getKey();
		
		Query q_to = new Query(ACCOUNT_KIND);
		q_to.setKeysOnly();
		q_to.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, to);
		PreparedQuery to_key = datastore.prepare(q_to);
		Entity e_to = to_key.asSingleEntity();
		if(e_to == null)
			return false;
		Key key_to = e_to.getKey();
		
		
		Query s_to = new Query(SUBSCRIPTION_KIND);
		s_to.setAncestor(key_to);
		s_to.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, from);
		PreparedQuery pq_to = datastore.prepare(s_to);
		Entity sub_to = pq_to.asSingleEntity();
		if(sub_to == null || !sub_to.getProperty(SUBSCRIPTION_STATUS_PROPERTY).equals(SUBSCRIPTION_STATUS_WAITING))
			return false;
		sub_to.setProperty(SUBSCRIPTION_STATUS_PROPERTY, SUBSCRIPTION_STATUS_ACTIVE);
		
		Query s_from = new Query(SUBSCRIPTION_KIND);
		s_from.setAncestor(key_from);
		s_from.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, to);
		PreparedQuery pq_from = datastore.prepare(s_from);
		Entity sub_from = pq_from.asSingleEntity();
		if(sub_from == null || !sub_from.getProperty(SUBSCRIPTION_STATUS_PROPERTY).equals(SUBSCRIPTION_STATUS_PENDING))
			return false;
		sub_from.setProperty(SUBSCRIPTION_STATUS_PROPERTY, SUBSCRIPTION_STATUS_ACTIVE);
		Transaction txn = datastore.beginTransaction();
		datastore.put(sub_to);
		datastore.put(sub_from);
		txn.commit();
		return true;
	}
	
	public boolean declineSubscription(String from, String to){
		Query q_from = new Query(ACCOUNT_KIND);
		q_from.setKeysOnly();
		q_from.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, from);
		PreparedQuery from_key = datastore.prepare(q_from);
		Entity e_from = from_key.asSingleEntity();
		if(e_from == null)
			return false;
		Key key_from = e_from.getKey();
		
		Query q_to = new Query(ACCOUNT_KIND);
		q_to.setKeysOnly();
		q_to.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, to);
		PreparedQuery to_key = datastore.prepare(q_to);
		Entity e_to = to_key.asSingleEntity();
		if(e_to == null)
			return false;
		Key key_to = e_to.getKey();
		
		
		Query s_to = new Query(SUBSCRIPTION_KIND);
		s_to.setAncestor(key_to);
		s_to.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, from);
		s_to.setKeysOnly();
		PreparedQuery pq_to = datastore.prepare(s_to);
		Entity sub_to = pq_to.asSingleEntity();
		if(sub_to == null || !sub_to.getProperty(SUBSCRIPTION_STATUS_PROPERTY).equals(SUBSCRIPTION_STATUS_WAITING))
			return false;
		
		Query s_from = new Query(SUBSCRIPTION_KIND);
		s_from.setAncestor(key_from);
		s_from.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, to);
		s_from.setKeysOnly();
		PreparedQuery pq_from = datastore.prepare(s_from);
		Entity sub_from = pq_from.asSingleEntity();
		if(sub_from == null || !sub_from.getProperty(SUBSCRIPTION_STATUS_PROPERTY).equals(SUBSCRIPTION_STATUS_PENDING))
			return false;
		Transaction txn = datastore.beginTransaction();
		datastore.delete(sub_to.getKey());
		datastore.delete(sub_from.getKey());
		txn.commit();
		return true;
	}
	
	public List<SubscriptionInformationObject> getSubscriptions(String user, String type){
		List<SubscriptionInformationObject> subl = new ArrayList<SubscriptionInformationObject>();
		Query key_query = new Query(ACCOUNT_KIND);
		key_query.setKeysOnly();
		key_query.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, user);
		PreparedQuery pq_key = datastore.prepare(key_query);
		Entity e_user = pq_key.asSingleEntity();
		if(e_user == null)
			return subl;
		Key key = e_user.getKey();
		Query q_sub = new Query(SUBSCRIPTION_KIND);
		q_sub.setAncestor(key);
		if(type.equalsIgnoreCase(SUBSCRIPTION_STATUS_WAITING) || type.equalsIgnoreCase(SUBSCRIPTION_STATUS_PENDING)) {
			q_sub.addFilter(SUBSCRIPTION_STATUS_PROPERTY, FilterOperator.NOT_EQUAL, SUBSCRIPTION_STATUS_ACTIVE);
			q_sub.addSort(SUBSCRIPTION_STATUS_PROPERTY, SortDirection.DESCENDING);
		}
		else if (type.equalsIgnoreCase(SUBSCRIPTION_STATUS_ACTIVE))
			q_sub.addFilter(SUBSCRIPTION_STATUS_PROPERTY, FilterOperator.EQUAL, SUBSCRIPTION_STATUS_ACTIVE);
		PreparedQuery pq = datastore.prepare(q_sub);
		List<Entity> entityList = pq.asList(FetchOptions.Builder.withDefaults());
		for(Iterator<Entity> i = entityList.iterator(); i.hasNext();){
			Entity e = i.next();
			String email = (String) e.getProperty(SUBSCRIPTION_EMAIL_PROPERTY);
			String status = (String) e.getProperty(SUBSCRIPTION_STATUS_PROPERTY);
			subl.add(new SubscriptionInformationObject(email,status));
		}
		return subl;
	}
	
	public boolean publishFeed(String email, String message){
		Query key_query = new Query(ACCOUNT_KIND);
		key_query.setKeysOnly();
		key_query.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, email);
		PreparedQuery pq_key = datastore.prepare(key_query);
		Entity e_from = pq_key.asSingleEntity();
		if(e_from == null)
			return false;
		Key key = e_from.getKey();
		Query q_sub = new Query(SUBSCRIPTION_KIND);
		q_sub.setAncestor(key);
		PreparedQuery pq = datastore.prepare(q_sub);
		List<Entity> entityList = pq.asList(FetchOptions.Builder.withDefaults());
		for(Iterator<Entity> i = entityList.iterator(); i.hasNext();){
			Entity e = i.next();
			String to_email = (String) e.getProperty(SUBSCRIPTION_EMAIL_PROPERTY);
			addFeed(to_email,email,message);
		}
		return true;
	}
	
	//add feed
	private boolean addFeed(String subscriber, String sender, String message){
		Query key_query = new Query(ACCOUNT_KIND);
		key_query.setKeysOnly();
		key_query.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, subscriber);
		PreparedQuery pq_key = datastore.prepare(key_query);
		Entity e_subscriber = pq_key.asSingleEntity();
		if(e_subscriber == null)
			return false;
		Key sub_key = e_subscriber.getKey();
		Query q_sub_sender = new Query(SUBSCRIPTION_KIND);
		q_sub_sender.setAncestor(sub_key);
		q_sub_sender.setKeysOnly();
		q_sub_sender.addFilter(SUBSCRIPTION_EMAIL_PROPERTY, FilterOperator.EQUAL, sender);
		q_sub_sender.addFilter(SUBSCRIPTION_STATUS_PROPERTY, FilterOperator.EQUAL, "Active");
		PreparedQuery pq_sender = datastore.prepare(q_sub_sender);
		Entity sender_entity = pq_sender.asSingleEntity();
		if(sender_entity == null)
			return false;
		Key sender_key = sender_entity.getKey();
		Transaction txn = datastore.beginTransaction();
		Entity sender_feed = new Entity(FEED_KIND, sender_key);
		sender_feed.setProperty(FEED_READ_STATUS_PROPERTY, false);
		sender_feed.setProperty(FEED_MESSAGE_PROPERTY, new Text(message));
		sender_feed.setProperty(FEED_TIMESTAMP_PROPERTY, new Date());
		datastore.put(sender_feed);
		txn.commit();
		return true;
	}
	
	public List<SubscriptionFeedObject> readFeeds(String email, boolean setRead, boolean getUnreadOnly){
		List<SubscriptionFeedObject> feeds = new ArrayList<SubscriptionFeedObject>();
		Query q = new Query(ACCOUNT_KIND);
		q.setKeysOnly();
		q.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, email);
		PreparedQuery pq = datastore.prepare(q);
		Entity e = pq.asSingleEntity();
		if(e == null) {
			return feeds;
		}
		Key k = e.getKey();
		Query q_feed = new Query(FEED_KIND);
		q_feed.setAncestor(k);
		q_feed.addSort(FEED_TIMESTAMP_PROPERTY,SortDirection.DESCENDING);
		if(getUnreadOnly)
			q_feed.addFilter(FEED_READ_STATUS_PROPERTY, FilterOperator.EQUAL, false);
		PreparedQuery pq_feed = datastore.prepare(q_feed);
		List<Entity> entityList = pq_feed.asList(FetchOptions.Builder.withDefaults());
		for(Iterator<Entity> i = entityList.iterator(); i.hasNext();) {
			Entity e_feed = i.next();
			Text feed_message_t = (Text)e_feed.getProperty(FEED_MESSAGE_PROPERTY);
			String feed_message = feed_message_t.getValue();
			boolean feed_read = (Boolean)e_feed.getProperty(FEED_READ_STATUS_PROPERTY);
			Date feed_timestamp = (Date)e_feed.getProperty(FEED_TIMESTAMP_PROPERTY);
			feeds.add(new SubscriptionFeedObject(feed_read, feed_message, feed_timestamp));
			if(setRead) {
				e_feed.setProperty(FEED_READ_STATUS_PROPERTY, true);
				datastore.put(e_feed);
			}
				
		}
		return feeds;
		
	}
	
	public boolean addWorklistItem(String user, WorklistItemObject wio){
		if (!checkWorklistItemExists(user, wio)) {
			Query q_user = new Query(ACCOUNT_KIND);
			q_user.setKeysOnly();
			q_user.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, user);
			PreparedQuery pq = datastore.prepare(q_user);
			Entity e_user = pq.asSingleEntity();
			if (e_user == null)
				return false;
			Key k = e_user.getKey();
			Transaction txn = datastore.beginTransaction();
			Entity e_wli = new Entity(WORKLIST_ITEM_KIND, k);
			e_wli.setProperty(WORKLIST_ITEM_DEPT_PROPERTY, wio.getDeptId());
			e_wli.setProperty(WORKLIST_ITEM_COURSE_PROPERTY, wio.getCourseId());
			e_wli.setProperty(WORKLIST_ITEM_SECTION_PROPERTY, wio.getSectionId());
			if(spiderDatastore.querySectionFromId( wio.getDeptId(), wio.getCourseId(),wio.getSectionId()) == null)
				return false;
			datastore.put(e_wli);
			txn.commit();
		} else
			return false;
		return true;
	}
	
	public boolean checkWorklistItemExists(String user, WorklistItemObject wio){
		Query q_user = new Query(ACCOUNT_KIND);
		q_user.setKeysOnly();
		q_user.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, user);
		PreparedQuery pq = datastore.prepare(q_user);
		Entity e_user = pq.asSingleEntity();
		if(e_user == null)
			return false;
		Key k = e_user.getKey();
		Query q_wio = new Query(WORKLIST_ITEM_KIND);
		q_wio.setAncestor(k);
		q_wio.addFilter(WORKLIST_ITEM_DEPT_PROPERTY, FilterOperator.EQUAL, wio.getDeptId());
		q_wio.addFilter(WORKLIST_ITEM_COURSE_PROPERTY, FilterOperator.EQUAL, wio.getCourseId());
		q_wio.addFilter(WORKLIST_ITEM_SECTION_PROPERTY, FilterOperator.EQUAL, wio.getSectionId());
		q_wio.setKeysOnly();
		PreparedQuery pq_wio = datastore.prepare(q_wio);
		if(pq_wio.asSingleEntity() == null)
			return false;
		return true;
	}
	
	public boolean deleteWorklistItem(String user, WorklistItemObject wio){
			Query q_user = new Query(ACCOUNT_KIND);
			q_user.setKeysOnly();
			q_user.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, user);
			PreparedQuery pq = datastore.prepare(q_user);
			Entity e_user = pq.asSingleEntity();
			if (e_user == null)
				return false;
			Key k = e_user.getKey();
			Query q_wio = new Query(WORKLIST_ITEM_KIND);
			q_wio.setAncestor(k);
			q_wio.setKeysOnly();
			q_wio.addFilter(WORKLIST_ITEM_DEPT_PROPERTY, FilterOperator.EQUAL, wio.getDeptId());
			q_wio.addFilter(WORKLIST_ITEM_COURSE_PROPERTY, FilterOperator.EQUAL, wio.getCourseId());
			q_wio.addFilter(WORKLIST_ITEM_SECTION_PROPERTY, FilterOperator.EQUAL, wio.getSectionId());
			PreparedQuery pq_wio = datastore.prepare(q_wio);
			if(pq_wio.asSingleEntity() == null)
				return false;
			Transaction txn = datastore.beginTransaction();
			datastore.delete(pq_wio.asSingleEntity().getKey());
			txn.commit();
			return true;
	}
	
	public List<SectionInformationObject> getWorklistAsSIO(String user){
		List<SectionInformationObject> siol = new ArrayList<SectionInformationObject>();
		Query q_user = new Query(ACCOUNT_KIND);
		q_user.setKeysOnly();
		q_user.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, user);
		PreparedQuery pq = datastore.prepare(q_user);
		Entity e_user = pq.asSingleEntity();
		if(e_user == null)
			return siol;
		Key k = e_user.getKey();
		Query q = new Query(WORKLIST_ITEM_KIND);
		q.setAncestor(k);
		PreparedQuery pq_wl = datastore.prepare(q);
		List<Entity> el = pq_wl.asList(FetchOptions.Builder.withDefaults());
		for(Iterator<Entity> i = el.iterator(); i.hasNext(); ) {
			Entity e = i.next();
			String dept = (String) e.getProperty(WORKLIST_ITEM_DEPT_PROPERTY);
			String course = (String)e.getProperty(WORKLIST_ITEM_COURSE_PROPERTY);
			String section = (String)e.getProperty(WORKLIST_ITEM_SECTION_PROPERTY);
			SectionInformationObject sio = spiderDatastore.querySectionFromId(dept, course, section);
			siol.add(sio);
		}
		
		return siol;
	}
	
	public List<WorklistItemObject> getWorklistAsWIO(String user){
		List<WorklistItemObject> wiol = new ArrayList<WorklistItemObject>();
		Query q_user = new Query(ACCOUNT_KIND);
		q_user.setKeysOnly();
		q_user.addFilter(ACCOUNT_ID_PROPERTY, FilterOperator.EQUAL, user);
		PreparedQuery pq = datastore.prepare(q_user);
		Entity e_user = pq.asSingleEntity();
		if(e_user == null)
			return wiol;
		Key k = e_user.getKey();
		Query q = new Query(WORKLIST_ITEM_KIND);
		q.setAncestor(k);
		PreparedQuery pq_wl = datastore.prepare(q);
		List<Entity> el = pq_wl.asList(FetchOptions.Builder.withDefaults());
		for(Iterator<Entity> i = el.iterator(); i.hasNext(); ) {
			Entity e = i.next();
			String dept = (String) e.getProperty(WORKLIST_ITEM_DEPT_PROPERTY);
			String course = (String)e.getProperty(WORKLIST_ITEM_COURSE_PROPERTY);
			String section = (String)e.getProperty(WORKLIST_ITEM_SECTION_PROPERTY);
			WorklistItemObject wio = new WorklistItemObject(dept,course,section);
			wiol.add(wio);
		}
		return wiol;
	}
	
}
